package com.roger.homecenterscreen.voice

import android.content.Context
import android.util.Log
import android.os.Handler
import android.os.Looper
import com.alibaba.idst.nui.Constants
import com.alibaba.idst.nui.INativeStreamInputTtsCallback
import com.alibaba.idst.nui.NativeNui
import org.json.JSONObject
import com.roger.homecenterscreen.config.BusinessConfig
import okhttp3.OkHttpClient
import okhttp3.Request
import okhttp3.RequestBody.Companion.toRequestBody
import java.util.concurrent.TimeUnit

/**
 * CosyVoice TTS 管理器（替换AIKIT TTS）
 * - 支持单次和流式文本
 */
class CosyVoiceTtsManager(
    private val context: Context,
    private val voiceManager: VoiceManager
) {
    private val TAG = "CosyVoiceTtsManager"
    private var nui: NativeNui? = null
    private var player: CosyAudioPlayer? = null
    private var streamingActive: Boolean = false
    private var streamingCallback: INativeStreamInputTtsCallback? = null

    fun initialize(): Boolean {
        return try {
            BusinessConfig.load(context)
            player = CosyAudioPlayer(BusinessConfig.cosyVoiceSampleRate)
            player?.start()

            // 使用流式TTS模式
            nui = NativeNui(Constants.ModeType.MODE_STREAM_INPUT_TTS)
            Log.i(TAG, "CosyVoice NativeNui created")
            true
        } catch (e: Exception) {
            Log.e(TAG, "CosyVoice init error", e)
            false
        }
    }

    fun release() {
        try { player?.stop() } catch (_: Exception) {}
        player = null
        try { nui?.release() } catch (_: Exception) {}
        nui = null
        streamingActive = false
        streamingCallback = null
    }

    /**
     * 单次合成：内部以流式方式发送整段文本
     */
    fun synthesize(text: String, onCompleted: (Boolean) -> Unit) {
        synthesizeStream(text, onCompleted)
    }

    /**
     * 流式合成：可多次调用以发送文本片段；最后一次回调携带完成标记
     */
    fun synthesizeStream(text: String, onCompleted: (Boolean) -> Unit) {
        val n = nui ?: kotlin.run {
            Log.w(TAG, "NativeNui not initialized")
            onCompleted(true)
            return
        }
        var apiKey = BusinessConfig.cosyVoiceApiKey
        if (apiKey.isNullOrBlank()) {
            Log.e(TAG, "CosyVoice apikey missing")
            onCompleted(true)
            return
        }
        if (!apiKey.startsWith("st-")) {
            try {
                val client = OkHttpClient.Builder()
                    .connectTimeout(10, TimeUnit.SECONDS)
                    .readTimeout(10, TimeUnit.SECONDS)
                    .writeTimeout(10, TimeUnit.SECONDS)
                    .build()
                val url = "https://dashscope.aliyuncs.com/api/v1/tokens?expire_in_seconds=1800"
                val req = Request.Builder()
                    .url(url)
                    .post("".toRequestBody(null))
                    .header("Authorization", "Bearer $apiKey")
                    .build()
                val resp = client.newCall(req).execute()
                val body = resp.body?.string()
                if (resp.isSuccessful && body != null) {
                    val json = JSONObject(body)
                    val token = json.optString("token", "")
                    if (token.startsWith("st-")) {
                        apiKey = token
                    } else {
                        Log.e(TAG, "CosyVoice temporary token invalid")
                        onCompleted(true)
                        return
                    }
                } else {
                    Log.e(TAG, "CosyVoice temporary token request failed ${resp.code}")
                    onCompleted(true)
                    return
                }
            } catch (e: Exception) {
                Log.e(TAG, "CosyVoice temporary token error", e)
                onCompleted(true)
                return
            }
        }
        // 生成鉴权票据（ticket）与参数（parameters）
        val ticket = JSONObject().apply {
            // 根据官方示例，仅使用 apikey 进行临时鉴权，不传 token
            // 注意：不要在端侧硬编码长效密钥，应使用服务端下发的临时 apikey
            put("apikey", apiKey)
            put("url", BusinessConfig.cosyVoiceUrl)
            put("device_id", "home-center-screen")
            put("complete_waiting_ms", 10000)
        }.toString()

        val params = JSONObject().apply {
            put("model", BusinessConfig.cosyVoiceModel)
            put("voice", BusinessConfig.cosyVoiceVoice)
            put("format", BusinessConfig.cosyVoiceFormat)
            if (BusinessConfig.cosyVoiceFormat == "opus" || BusinessConfig.cosyVoiceFormat == "mp3") {
                put("enable_audio_decoder", true)
            } else {
                put("enable_audio_decoder", false)
            }
            put("sample_rate", BusinessConfig.cosyVoiceSampleRate)
        }.toString()

        val cb = object : INativeStreamInputTtsCallback {
            override fun onStreamInputTtsEventCallback(
                event: INativeStreamInputTtsCallback.StreamInputTtsEvent?,
                task_id: String?,
                session_id: String?,
                ret_code: Int,
                error_msg: String?,
                timestamp: String?,
                all_response: String?
            ) {
                if (event == INativeStreamInputTtsCallback.StreamInputTtsEvent.STREAM_INPUT_TTS_EVENT_SYNTHESIS_COMPLETE ||
                    event == INativeStreamInputTtsCallback.StreamInputTtsEvent.STREAM_INPUT_TTS_EVENT_TASK_FAILED) {
                    if (!all_response.isNullOrEmpty()) {
                        try {
                            val obj = org.json.JSONObject(all_response)
                            val header = obj.optJSONObject("header")
                            val code = header?.optString("error_code")
                            val msg = header?.optString("error_message")
                            if (!code.isNullOrBlank() || !msg.isNullOrBlank()) {
                                Log.e(TAG, "CosyVoice event error: code=$code msg=$msg")
                            }
                        } catch (_: Exception) {}
                    }
                    Handler(Looper.getMainLooper()).post { onCompleted(true) }
                }
            }

            override fun onStreamInputTtsDataCallback(data: ByteArray?) {
                if (data == null || data.isEmpty()) return
                player?.writePcm(data)
            }

            override fun onStreamInputTtsLogTrackCallback(level: Constants.LogLevel?, log: String?) {
                // 可根据需要输出日志
                if (log != null) Log.d(TAG, "CosyVoice log: $log")
            }
        }

        val uuid = java.util.UUID.randomUUID().toString()

        // 启动流式（回调、ticket、parameters、debugPath、logLevel、saveLog）
        n.startStreamInputTts(cb, ticket, params, uuid, Constants.LogLevel.toInt(Constants.LogLevel.LOG_LEVEL_INFO), false)
        // 发送文本（整段或片段均可）
        n.sendStreamInputTts(text)
        // 结束
        n.asyncStopStreamInputTts()
    }

    /**
     * 开始一个持久的流式会话，供多次追加文本。
     */
    fun startStreaming(onCompleted: (Boolean) -> Unit) {
        val n = nui ?: kotlin.run {
            Log.w(TAG, "NativeNui not initialized")
            onCompleted(true)
            return
        }
        if (streamingActive) return
        val apiKey = BusinessConfig.cosyVoiceApiKey
        if (apiKey.isNullOrBlank() || !apiKey.startsWith("st-")) {
            Log.e(TAG, "CosyVoice apikey invalid or not temporary (expect st- prefix)")
            onCompleted(true)
            return
        }
        val ticket = JSONObject().apply {
            put("apikey", apiKey)
            put("url", BusinessConfig.cosyVoiceUrl)
            put("device_id", "home-center-screen")
            put("complete_waiting_ms", 10000)
        }.toString()
        val params = JSONObject().apply {
            put("model", BusinessConfig.cosyVoiceModel)
            put("voice", BusinessConfig.cosyVoiceVoice)
            put("format", BusinessConfig.cosyVoiceFormat)
            if (BusinessConfig.cosyVoiceFormat == "opus" || BusinessConfig.cosyVoiceFormat == "mp3") {
                put("enable_audio_decoder", true)
            } else {
                put("enable_audio_decoder", false)
            }
            put("sample_rate", BusinessConfig.cosyVoiceSampleRate)
        }.toString()

        val cb = object : INativeStreamInputTtsCallback {
            override fun onStreamInputTtsEventCallback(
                event: INativeStreamInputTtsCallback.StreamInputTtsEvent?,
                task_id: String?,
                session_id: String?,
                ret_code: Int,
                error_msg: String?,
                timestamp: String?,
                all_response: String?
            ) {
                if (event == INativeStreamInputTtsCallback.StreamInputTtsEvent.STREAM_INPUT_TTS_EVENT_SYNTHESIS_COMPLETE ||
                    event == INativeStreamInputTtsCallback.StreamInputTtsEvent.STREAM_INPUT_TTS_EVENT_TASK_FAILED) {
                    streamingActive = false
                    Handler(Looper.getMainLooper()).post { onCompleted(true) }
                }
            }

            override fun onStreamInputTtsDataCallback(data: ByteArray?) {
                if (data == null || data.isEmpty()) return
                player?.writePcm(data)
            }

            override fun onStreamInputTtsLogTrackCallback(level: Constants.LogLevel?, log: String?) {
                if (log != null) Log.d(TAG, "CosyVoice log: $log")
            }
        }
        streamingCallback = cb
        n.startStreamInputTts(cb, ticket, params, "", Constants.LogLevel.toInt(Constants.LogLevel.LOG_LEVEL_INFO), false)
        streamingActive = true
    }

    /**
     * 追加文本到当前流式会话。
     */
    fun appendStreaming(text: String) {
        val n = nui ?: return
        if (!streamingActive) return
        n.sendStreamInputTts(text)
    }

    /**
     * 结束当前流式会话。
     */
    fun finishStreaming() {
        val n = nui ?: return
        if (!streamingActive) return
        n.asyncStopStreamInputTts()
    }
}